﻿#ifndef WRWORKTCPCOMMCLIENTWORKDEALER
#define WRWORKTCPCOMMCLIENTWORKDEALER

#include "WRWorkTcpCommClientInterface.h"
#include "WRWorkTcpCommClientInterfaceActivator.h"
#include "../WRWorkTcpComm.h"
#include "../WRWorkTcpCommConsts.h"
#include "../WRWorkDealer.h"
#include "../../WRSoft-Utility/Runtime/WRDataPacket.h"

#include <QMutex>
#include <QSemaphore>

/********************
class Writer
{
public:
    int count(const T& val);
    int write(const T& val, unsigned char* buf);
};
********************/

//表示工作TCP通讯客户端工作处理接口。
template <class T, class TWriter>
class WRWorkTcpCommClientWorkDealer : public WRWorkTcpCommClientInterface, public WRWorkDealer
{
private:
    //表示处理项目。
    class ProcEntry
    {
    private:
        int m_serial;
        int m_result;
        WRWorkAffair* m_affair;
        QSemaphore m_mutex;

    public:
        //初始化处理项目。
        inline ProcEntry(int serial)
            : m_serial(serial), m_result(WRErrors::Timeout), m_affair(0)
        {
            //add code here
        }

        //获取序号。
        inline int serial(void) const
        {
            return m_serial;
        }
        //获取结果。
        inline int result(void) const
        {
            return m_result;
        }
        //获取事务。
        inline WRWorkAffair* affair(void) const
        {
            return m_affair;
        }

        //等待完成。
        inline bool wait(int timeout = 10000)
        {
            return m_mutex.tryAcquire(1, timeout);
        }
        //完成处理。
        inline void fulfil(int result, WRWorkAffair* affair = 0)
        {
            m_result = result;
            m_affair = affair;
            m_mutex.release();
        }
    };

    QMutex m_mutex;
    int m_timeout;
    int m_sequence;
    TWriter m_writer;
    ProcEntry* m_procEntry;
    QMutex m_procMutex;

public:
    //初始化工作TCP通讯客户端工作处理接口。
    WRWorkTcpCommClientWorkDealer(const QUuid& uuid, const QString& name, int index, WRWorkTcpCommClientObject* target, int timeout = WRWorkTcpComm::DefaultTimeount)
        : WRWorkTcpCommClientInterface(uuid, name, index, target), m_timeout(timeout), m_sequence(0), m_procEntry(0)
    {
        //add code here
    }
    //初始化工作TCP通讯客户端工作处理接口。
    WRWorkTcpCommClientWorkDealer(const QUuid& uuid, const QString& name, int index, WRWorkTcpCommClientAffair* target, int timeout = WRWorkTcpComm::DefaultTimeount)
        : WRWorkTcpCommClientInterface(uuid, name, index, target), m_timeout(timeout), m_sequence(0), m_procEntry(0)
    {
        //add code here
    }

    //清理当前对象所占用的相关资源。
    ~WRWorkTcpCommClientWorkDealer(void)
    {
        //add code here
    }

    //创建当前接口的新接口。
    WRWorkTcpCommClientInterface* clone(WRWorkTcpCommClientObject* target)
    {
        return new WRWorkTcpCommClientWorkDealer(uuid(), name(), index(), target, m_timeout);
    }
    //创建当前接口的新接口。
    WRWorkTcpCommClientInterface* clone(WRWorkTcpCommClientAffair* target)
    {
        return new WRWorkTcpCommClientWorkDealer(uuid(), name(), index(), target, m_timeout);
    }

    //创建工作事例。
    WR32s create(const void* params, WRWorkAffair** target)
    {
        *target = 0;
        QMutexLocker lck(&m_mutex);

        WRWorkTcpCommClientSession* session = object()->session();
        if (session->effective())
        {
            ++m_sequence;

            int argsLen = m_writer.count(*(const T*)params);
            int fillLen = 0;//填充长度
            {
                int remain = argsLen % 8;
                if (remain > 0) fillLen = 8 - remain;
            }

            WRDataPacket* packet;
            if (affair())
            {
                char* p;
                int cmdLen = 40 + argsLen + fillLen;
                packet = WRDataPacket::create(cmdLen);
                packet->buffer(&p);

                WRBytes::write((WR32u)WRWorkTcpComm::FrameHeader, p);//帧头
                p += 4;
                WRBytes::write((WR32s)(cmdLen), p);//帧长度
                p += 4;
                WRBytes::write((WR16u)(object()->index()), p);//工作对象索引
                p += 2;
                WRBytes::write((WR16u)WRWorkTcpComm::WorkObjectAffair, p);//类型（工作事务）
                p += 2;
                WRBytes::write((WR32s)(affair()->id()), p);
                p += 4;
                WRBytes::write((WR16u)(affair()->index()), p);//工作对象索引
                p += 2;
                WRBytes::write((WR16u)WRWorkTcpComm::WorkAffairIITreat, p);//类型（接口处理）
                p += 2;
                WRBytes::write((WR16u)(index()), p);//接口索引
                p += 4;
                WRBytes::write((WR32s)(m_sequence), p);//指令序号
                p += 4;
                WRBytes::write((WR32s)(argsLen), p);//参数长度
                p += 4;
                m_writer.write(*(const T*)params, (unsigned char*)p);//参数数据
                p += argsLen;
                p += fillLen; ;
                WRBytes::write((WR32u)WRWorkTcpComm::FrameVersion, p);//版本
                p += 4;
                WRBytes::write((WR32u)WRWorkTcpComm::FrameTailor, p);//帧尾
            }
            else
            {
                char* p;
                int cmdLen = 32 + argsLen + fillLen;
                packet = WRDataPacket::create(cmdLen);
                packet->buffer(&p);

                WRBytes::write((WR32u)WRWorkTcpComm::FrameHeader, p);//帧头
                p += 4;
                WRBytes::write((WR32s)(cmdLen), p);//帧长度
                p += 4;
                WRBytes::write((WR16u)(object()->index()), p);//工作对象索引
                p += 2;
                WRBytes::write((WR16u)WRWorkTcpComm::WorkObjectIITreat, p);//类型（接口处理）
                p += 2;
                WRBytes::write((WR16u)(index()), p);//接口索引
                p += 4;
                WRBytes::write((WR32s)(m_sequence), p);//指令序号
                p += 4;
                WRBytes::write((WR32s)(argsLen), p);//参数长度
                p += 4;
                m_writer.write(*(const T*)params, (unsigned char*)p);//参数数据
                p += argsLen;
                p += fillLen; ;
                WRBytes::write((WR32u)WRWorkTcpComm::FrameVersion, p);//版本
                p += 4;
                WRBytes::write((WR32u)WRWorkTcpComm::FrameTailor, p);//帧尾
            }

            m_procMutex.lock();
            if (!session->sendData(packet))
            {
                packet->release();
            }
            else
            {
                m_procEntry = new ProcEntry(m_sequence);
            }
            m_procMutex.unlock();
        }

        int result = WRErrors::Timeout;
        if (m_procEntry)
        {
            m_procEntry->wait(m_timeout);
            m_procMutex.lock();
            {
                result = m_procEntry->result();
                *target = m_procEntry->affair();
                delete m_procEntry;
                m_procEntry = 0;
            }
            m_procMutex.unlock();
        }
        return result;
    }

    //处理数据。
    void procData(const unsigned char* buf, int len)
    {
        buf += 2;
        len -= 2;
        WR32s serial = WRBytes::read<WR32s>(buf);
        buf += 4;
        len -= 4;

        m_procMutex.lock();
        if (m_procEntry && m_procEntry->serial() == serial)
        {
            WR32s result = WRBytes::read<WR32s>(buf);
            buf += 4;
            len -= 4;
            WRWorkAffair* affair = 0;
            if (result == WRErrors::None)
            {
                WR32s index = WRBytes::read<WR32s>(buf);
                buf += 4;
                len -= 4;
                WR32s id = WRBytes::read<WR32s>(buf);

                affair = object()->createAffair(id, index);
            }
            m_procEntry->fulfil(result, affair);
        }
        m_procMutex.unlock();
    }

    //获取工作处理接口。
    WRWorkDealer* workDealer(void)
    {
        return this;
    }
};

//表示工作TCP通讯客户端业务处理激活器。
template <class T, class TWriter, class TUuidValue, class TNameValue>
class WRWorkTcpCommClientWorkDealerActivator : public WRWorkTcpCommClientInterfaceActivator
{
public:
    //初始化工作TCP通讯客户端业务处理激活器。
    WRWorkTcpCommClientWorkDealerActivator(void)
    {
        TUuidValue uuid;
        WRWorkTcpComm::enrollClientInterface(uuid(), this);
    }
    //释放当前对象所占用的相关资源。
    ~WRWorkTcpCommClientWorkDealerActivator(void)
    {
        TUuidValue uuid;
        WRWorkTcpComm::cancelClientInterface(uuid());
    }

    //创建接口实例。
    WRWorkTcpCommClientInterface* create(int index, WRWorkTcpCommClientObject* target)
    {
        TUuidValue uuid;
        TNameValue name;
        return new WRWorkTcpCommClientWorkDealer<T, TWriter>(uuid(), name(), index, target);
    }
    //创建接口实例。
    WRWorkTcpCommClientInterface* create(int index, WRWorkTcpCommClientAffair* target)
    {
        TUuidValue uuid;
        TNameValue name;
        return new WRWorkTcpCommClientWorkDealer<T, TWriter>(uuid(), name(), index, target);
    }
};

#endif // WRWORKTCPCOMMCLIENTWORKDEALER

